# -*- coding: utf-8 -*-
# File Name：     stock_factor_market_customized_api
# Author :       thinkive_cfy_ide_3
# date：          2020/10/22
# Description :

import pandas as pd
from quant_researcher.quant.datasource_fetch.index_api import index_price_related
from quant_researcher.quant.datasource_fetch.factor_api import factor_info, factor_exposure_related
from quant_researcher.quant.project_tool.db_operator import db_conn
from quant_researcher.quant.performance_attribution.core_functions.performance_analysis.performance import sharpe_ratio
from quant_researcher.quant.datasource_fetch.index_api import index_components
from quant_researcher.quant.factors.factor_analysis.factor_analyser.factor_analyse import FactorAnalyseMachine
from quant_researcher.quant.factors.factor_analysis.factor_contribution.fac_contribution import fac_contribution_calc


def customized_factor_market(external_data):
    """
    自定义因子的因子集市界面数据

    :param external_data: 外部因子数据，确认数据中至少包含tradedate，stockcode和因子名称三列，多个因子在列上扩充
        一个包含ROE指标的数据形状如下：
        —————————————
        stockcode|tradedate|roe
        000001|2010-01-03| 0.2
        000002|2010-01-03| 0.15
    :return:
    """
    con_mfdb = db_conn.get_basic_data_conn(by_sqlalchemy=True)
    factor_list = external_data.columns.difference(['tradedate','stockcode']).tolist()
    begin_date = external_data['tradedate'].min()
    end_date = external_data['tradedate'].max()
    factor_machine = FactorAnalyseMachine(begin_date=begin_date,
                                          end_date=end_date,
                                          asset_type='stock',
                                          external_data=True,
                                          factor_data=external_data)
    factor_machine.param_setting(period='monthly',
                                 benchmark='000985')
    factor_machine.initial_data()
    ic_ir_result = factor_machine.time_range_ic(period='monthly', plot=False)
    avg_ic = ic_ir_result[0].iloc[:, 0].mean()
    ir = ic_ir_result[1]
    _, _, _, group_return = factor_machine.longshort_portfolio(period='monthly', plot=False)
    long_ret_data = group_return[5]
    long_short_ret_data = group_return[5] - group_return[1]
    long_short_cum_ret = ((long_short_ret_data + 1).cumprod() - 1).iloc[-1]
    long_cum_ret = ((long_ret_data + 1).cumprod() - 1).iloc[-1]
    long_sharpe = sharpe_ratio(long_ret_data)
    # benchmark = index_price_related.get_index_close('000985', long_short_ret_data.index.min(), long_short_ret_data.index.max())
    benchmark = index_price_related.get_index_close(
        index_code='000985',
        start_date=long_short_ret_data.index.min(),
        end_date=long_short_ret_data.index.max()
    ).rename(columns={'end_date': 'trade_date'}).set_index(['trade_date', 'index_code'])['close'].unstack()
    benchmark.index = pd.to_datetime(benchmark.index)
    benchmark = benchmark.rename(columns={'trade_date': 'tradedate', 'index_code': 'indexcode'})
    bench_ret = benchmark.set_index('tradedate')['price_to'].ffill().pct_change()
    bench_cum_ret = (bench_ret + 1).cumprod() - 1
    long_active_cum_ret = long_cum_ret - bench_cum_ret.iloc[-1]
    # 计算因子贡献率
    contri_data = fac_contribution_calc(factor_list, begin_date, end_date, external_data=external_data)
    avg_contri = contri_data.abs().mean()
    result = dict()
    result['long_short_cum_ret'] = long_short_cum_ret
    result['long_active_cum_ret'] = long_active_cum_ret
    result['long_sharpe'] = long_sharpe
    result['avg_ic'] = avg_ic
    result['ir'] = ir.iloc[-1]
    result['avg_contri'] = avg_contri.iloc[-1]
    result['factor_direction'] = 1 if avg_ic > 0 else 0
    return result


if __name__ == '__main__':
    CON = db_conn.get_derivative_data_conn(by_sqlalchemy=True)
    CON_astk = db_conn.get_stock_conn(by_sqlalchemy=True)
    CON_factor = db_conn.get_tk_factors_conn(by_sqlalchemy=True)
    factor = 'etop'
    begin_date = '2020-01-29'
    end_date = '2020-05-01'
    asset_pool = index_components.get_index_hist_stock_pool('000300', begin_date, end_date)['stock_code'].tolist()
    factor_table_name = factor_info.get_factor_table_name(factor)[0]
    # temp = factor_exposure_related.get_stock_factor_exposure(factor, asset_pool, begin_date, end_date)
    temp = factor_exposure_related.get_stock_factor_exposure(factor, asset_pool, begin_date, end_date)
    temp = temp.rename(columns={'end_date': 'tradedate', 'stock_code': 'stockcode'})
    result = customized_factor_market(temp)




